home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-11-24 | 38.4 KB | 1,352 lines |
- .\" Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984.
- .Du START
- .sp 1
- .in 0
- .ce 99
- DESCRIPTION OF B
-
- Lambert Meertens
- Steven Pemberton
-
- CWI
- Amsterdam
-
- April 1984
- .ce 0
- .Co
- .ds Sn Contents
- .bp
- .in 15
- .nf
- .ps 8
- .vs 10
- CONTENTS
-
- 0.\0INTRODUCTION
- 1.\0VALUES IN B
- 2.\0SYNTAX DESCRIPTION METHOD
- 3.\0REPRESENTATIONS
- 4.\0UNITS
- 4.1.\0HOW-TO-UNITS
- 4.2.\0YIELD-UNITS
- 4.3.\0TEST-UNITS
- 4.4.\0REFINEMENTS
- 4.5.\0COMMAND-SUITES
- 5.\0COMMANDS
- 5.1.\0\0SIMPLE-COMMANDS
- 5.1.1.\0\0CHECK-COMMANDS
- 5.1.2.\0\0WRITE-COMMANDS
- 5.1.3.\0\0READ-COMMANDS
- 5.1.4.\0\0PUT-COMMANDS
- 5.1.5.\0\0DRAW-COMMANDS
- 5.1.6.\0\0CHOOSE-COMMANDS
- 5.1.7.\0\0SET-RANDOM-COMMANDS
- 5.1.8.\0\0REMOVE-COMMANDS
- 5.1.9.\0\0INSERT-COMMANDS
- 5.1.10.\0DELETE-COMMANDS
- 5.1.11.\0QUIT-COMMAND
- 5.1.12.\0RETURN-COMMANDS
- 5.1.13.\0SUCCEED-COMMAND
- 5.1.14.\0FAIL-COMMAND
- 5.1.15.\0USER-DEFINED-COMMANDS
- 5.1.16.\0REFINED-COMMANDS
- 5.2.\0CONTROL-COMMANDS
- 5.2.1.\0IF-COMMANDS
- 5.2.2.\0SELECT-COMMANDS
- 5.2.3.\0WHILE-COMMANDS
- 5.2.4.\0FOR-COMMANDS
- 6.\0EXPRESSIONS, TARGETS AND TESTS
- 6.1.\0EXPRESSIONS
- 6.1.1.\0NUMERIC-CONSTANTS
- 6.1.2.\0TARGET-CONTENTS
- 6.1.3.\0TRIMMED-TEXTS
- 6.1.4.\0TABLE-SELECTIONS
- 6.1.5.\0DISPLAYS
- 6.1.6.\0FORMULAS
- Formulas with user-defined functions
- Formulas with predefined functions
- 6.1.7.\0REFINED-EXPRESSIONS
- 6.2.\0TARGETS
- 6.2.1.\0IDENTIFIERS
- 6.2.2.\0TRIMMED-TEXT-TARGETS
- 6.2.3.\0TABLE-SELECTION-TARGETS
- 6.3.\0TESTS
- 6.3.1.\0ORDER-TESTS
- 6.3.2.\0PROPOSITIONS
- Propositions with user-defined predicates
- Propositions with predefined predicates
- 6.3.3.\0REFINED-TESTS
- 6.3.4.\0CONJUNCTIONS
- 6.3.5.\0DISJUNCTIONS
- 6.3.6.\0NEGATIONS
- 6.3.7.\0QUANTIFICATIONS
- INDEX
- .ps 10
- .vs 12
- .in 0
- .ds Sn Introduction
- .bp
- .St 0 INTRODUCTION
- .fi
- .Tx
- \*B is a simple but powerful new programming language, designed for use in
- personal computing.
- (Note: the name ``\*B'' is only a temporary working title,
- and the new language bears no relation to the predecessor of
- C.)\
- The foremost aim in the design of \*B has been the ease of use for
- programmers who want to produce working programs without having
- to master a complex tool.
- An implementation of \*B is available from the \*B group at
- the CWI, currently only under UNIX* or its look-alikes, but soon
- (scheduled early 1985) also for the IBM-PC under MS-DOS.
- Remarks concerning the implementation appear in this description
- between double braces {{ and }}.
- .sp 0.6v
- This description of \*B originated from a text, prepared by
- the first author, for use in teaching \*B during the Fall
- term of 1982 at New York University.
- The aim is to provide a reference book for the users of \*B that is more
- accessible than the somewhat formal ``Draft Proposal'' [2].
- While it is not a text book, it should also be useful
- to people who already have ample programming
- experience and want to learn \*B.
- A text book for beginners is also available from the CWI [1].
- .sp 0.6v
- In this description we have tried to remain close to the Draft Proposal
- in order to facilitate cross-referencing. To this end, all section numbers
- from section 4 onwards are the same as in the Draft Proposal.
- However there are some changes in terminology.
- Some minor differences are
- .sp 0.6v
- .ta 2m \w'mmTYPE-TYPES-expressionmm'u \w'mmTYPE-TYPES-expressionmm'u+\w'multiple-expressionmm'u
- .nf
- \& Draft Proposal: This description:
- .sp 0.4v
- \& textual-display text-display
- \& textual-body text-body
- \& LIST-body optional-list-body
- \& TABLE-body optional-table-filler-series
- .fi
- .sp 0.6v
- But the main difference is perhaps in the treatment of ``collateral'':
- .sp 0.6v
- .nf
- \& Draft Proposal: This description: Examples
- .sp 0.4v
- \& collateral-expression expression \*(<:a (a, b) a, b\*(:>
- \& TYPE-expression single-expression \*(<:a (a, b)\*(:>
- \& TYPE-TYPES-expression multiple-expression \*(<: a, b\*(:>
- .fi
- .sp 0.6v
- Whereas these are purely descriptional differences,
- there are also a few differences in content.
- Where the Draft Proposal has the keyword \*(<:ALLOW\*(:>,
- \*B now has the keyword \*(<:SHARE\*(:>;
- a command \*(<:READ\*(:>\ ...\ \*(<:RAW\*(:> has been added;
- and approximate-constants may no longer consist of just an exponent-part:
- \*(<:E-1\*(:> must now be written \*(<:1E-1\*(:>.
- .sp 0.6v
- References
- .sp 0.5v
- .in +\w'[1]\ 'u
- .ti 0
- [1]\ \fIComputer Programming for Beginners, Introducing the B Language,
- Part 1\fP,
- .br
- Leo Geurts, CWI, Amsterdam, 1984
- .sp 0.5v
- .ti 0
- [2]\ \fIDraft Proposal for the B Programming Language\fP,
- .br
- Lambert Meertens, CWI, Amsterdam, 1981
- .sp 0.6v
- .in 0
- *\ \s-2Unix is a trademark of Bell Laboratories.\s0
- .fi
- .SN 1
- .bp
- .St 1 "VALUES IN \*B"
- .de tY
- .sp 1
- .ne 5
- .in \w'Compounds\0\0'u
- .ta \w'Compounds\0\0'u
- .ti 0
- \\$1\t\c
- ..
- .Xx number
- .Xx exact number
- .Xx approximate number
- .Xx text
- .Xx character
- .Xx order
- .Xx compound
- .Xx field
- .Xx list
- .Xx entry
- .Xx list entry
- .Xx table
- .Xx table entry
- .Xx key
- .Xx associate
- .Tx
- \*B has two basic types of values: numbers and texts, and three ways of making
- new types of values from existing ones: compounds, lists and tables.
- The built-in functions for operating on these values are described
- in section 6.1.6 entitled ``Formulas with predefined functions''.
- .tY Numbers
- Numbers come in two kinds: exact and approximate.
- Exact numbers are rational numbers.
- For example, \*(<:1.25\*(:> = \*(<:5/4\*(:>, and \*(<:(1/3)*3\*(:> = \*(<:1\*(:>.
- There is no restriction on the size of numerator and denominator.
- Approximate numbers are implemented by whatever the hardware has to offer
- for fast but approximate arithmetic (floating point).
- .br
- The arithmetic operations and many other functions give an exact result
- when their operands are exact,
- and an approximate result otherwise,
- but the function \*(<:sin\*(:>, for example, always returns an approximate number.
- .br
- An exact number can be made approximate with the \*(<:~\*(:> function
- (e.g. \*(<:~1.25\*(:>);
- the functions \*(<:round\*(:>, \*(<:floor\*(:> and \*(<:ceiling\*(:> can be used to convert
- an approximate number to an exact one.
- .br
- Exact and approximate numbers may be mixed in arithmetic, as in \*(<:4 * atan 1\*(:>.
- .tY Texts
- Texts (strings) are composed of printable ASCII characters.
- They are variable length, and are ordered in the usual lexicographic way:
- \&\*(<:'a' < 'aa' < 'b'\*(:>.
- There is no type ``character'': a text of length one will do.
- .br
- The printable characters
- are the 95 characters represented on the lines below,
- where the blank space preceding `\*(<:!\*(:>' stands for the
- (otherwise invisible) space character:
- .Di 5
- \*(<: !"#$%&'()*+,-./0123456789:;<=>?
- @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_
- `abcdefghijklmnopqrstuvwxyz{|}~\*(:>
- .br
- .Ed
- The ordering
- on the characters is the ASCII collating order, which is the order
- in which the characters are displayed above.
- .tY Compounds
- A compound consists of a sequence of other values, its ``fields''.
- For example,
- the number \*(<:3\*(:> and the text \*(<:'xyz'\*(:> may be combined to give the
- compound \*(<:3, 'xyz'\*(:>.
- Compounds are also ordered lexicographically.
- .br
- For example, \*(<:(3, 'xyz') < (3, 'yz') < (pi, 'aaa')\*(:>.
- For this to be meaningful, the compounds that are compared must
- be of the same type.
- This means that they have the
- same number of fields, and that corresponding fields are of the same type.
- .br
- The only way to obtain the individual fields of a compound is to put it
- in a multiple-target with the right number of components, as in
- .Di 1
- \*(<:PUT name IN last'name, first'name, middle'name\*(:>.
- .Ed
- .tY Lists
- A list is a \fIsorted\fP sequence of values, its ``entries''.
- All entries of a list must be of the same type, and this determines
- the type of the list.
- The length of a list may vary without influencing its type.
- When an entry is inserted in a list (with an \*(<:INSERT\*(:> command), it is automatically
- inserted in the list in the proper position in the sorting order.
- A list may contain duplicates of the same entry.
- Entries may be removed with the \*(<:REMOVE\*(:> command.
- Again, lists themselves are ordered lexicographically.
- .tY Tables
- A table consists of a (sorted) sequence of ``table entries''.
- Each table entry is a pair of two values: a \fIkey\fP and an \fIassociate\fP.
- All keys of a table must be of the same type; similarly, all associates must
- also be of the same type (but that type may be different to
- that of the keys).
- A table may not contain duplicate keys.
- If \*(<:k\*(:> is a key of the table \*(<:t\*(:>, then \*(<:t[k]\*(:>
- gives the associate corresponding to \*(<:k\*(:>.
- New entries can be made, or existing entries modified, by putting the
- associate value in the table after selecting with the key value, as
- in \*(<:PUT a IN t[k]\*(:>.
- Entries can be deleted with the \*(<:DELETE\*(:> command, as in \*(<:DELETE t[k]\*(:>.
- The ordering is again lexicographic.
- .St 2 "SYNTAX DESCRIPTION METHOD"
- .Tx
- The syntax of \*B is given in the following form:
- each rule starts with the name of the thing being defined followed by a colon;
- following this are one or more alternatives,
- each marked with a \(bu in front.
- Each alternative is composed of symbols that stand for
- themselves, or the names of other rules.
- These other rules are then defined elsewhere in the grammar,
- or possibly in the same rule.
- As an example, here is a simple grammar for a small part of English:
- .Sy 4
- .Pn sentence 3
- .Al
- declarative
- .Al
- declarative \*(<:,\*(:> connective\0sentence
- .Pn declarative 3
- .Al
- collective-noun\0verb\0collective-noun
- .Al
- collective-noun \*(<:do not\*(:> verb\0collective-noun
- .Pn collective-noun 2
- .Al
- \*(<:cats\*(:>
- .Al
- \*(<:dogs\*(:>
- .Al
- \*(<:people\*(:>
- .Al
- \*(<:the police\*(:>
- .Pn verb 2
- .Al
- \*(<:love\*(:>
- .Al
- \*(<:hate\*(:>
- .Al
- \*(<:eat\*(:>
- .Al
- \*(<:hassle\*(:>
- .Pn connective 2
- .Al
- \*(<:and\*(:>
- .Al
- \*(<:but\*(:>
- .Al
- \*(<:although\*(:>
- .Al
- \*(<:because\*(:>
- .Al
- \*(<:yet\*(:>
- .Tx
- This produces sentences like:
- .Di 4
- .in -6
- \*(<:dogs do not love the police\*(:>
- \*(<:the police hassle dogs\*(:>
- \*(<:cats do not hate cats , but cats hate dogs , because dogs hate cats\*(:>
- \*(<:people eat dogs , yet dogs love people\*(:>
- .in +6
- .Ed
- .in 0
- You will notice that the names of rules are in a different
- typeface to words that stand for themselves.
- In the grammar of \*B that follows, furthermore, rule names
- are all in lower-case letters, while words that stand for themselves are all
- in upper-case letters, so they are easily distinguished.
- .sp
- It often happens that a part of an alternative is optional.
- There is a special rule for this:
- .Sy 4
- .Pr empty 2
- .Al
- .br
- .Pr optional-ANYTHING 3
- .Al
- empty
- .Al
- ANYTHING
- .Tx
- The ``optional'' rule is included to save many rules in the definition.
- For example, it stands for a rule
- .Pn optional-comment 3
- .Al
- empty
- .Al
- comment
- .Tx
- and similar rules.
- (Empty produces an empty result.)
- .St 3 REPRESENTATIONS
- .Xx indentation
- .Xx increase-indentation
- .Xx decrease-indentation
- .Xx new-line-proper
- .Xx keyword
- .Xx tag
- .Pr new-line 2
- .Sl
- optional-comment\0new-line-proper\0indent
- .Ps
- A \*B program consists of indented lines.
- A new-line-proper marks a transition to a new line.
- An indent stands for the left margin blank offset.
- Initially, the left margin has zero width.
- The indentation is increased by an increase-indentation
- and decreased again by a decrease-indentation.
- These always come in pairs and serve for grouping, just as BEGIN-END pairs
- do in other programming languages.
- An increase-indentation is always preceded by a line ending with a colon
- (possibly followed by comment).
- .Pr comment 3
- .Al
- optional-new-line-proper\0optional-spaces
- \*(<:\\\*(:> comment-body\0optional-further-comment
- .Pr further-comment 3
- .Al
- new-line-proper\0optional-spaces
- \*(<:\\\*(:> comment-body\0optional-further-comment
- .Pr spaces 2
- .Sl
- space\0optional-spaces
- .Ps
- Comments may be placed at the end of a line or may stand alone
- on a line.
- No comment may precede the first line of a unit (see section 4).
- .br
- A comment-body may be any sequence of printable characters.
- .Sx 2 comment:
- \*(<:\\modified 6/4/84 to reject passwords of length < 6\*(:>
- .Tx
- Keywords are composed of CAPITAL letters (\*(<:A\*(:> to \*(<:Z\*(:>), digits,
- and quotes (\*(<:'\*(:> and \*(<:"\*(:>).
- A keyword must start with a letter.
- For example, \*(<:A3'B"\*(:> is a keyword.
- .Tx
- Tags are composed of lower-case letters (\*(<:a\*(:> to \*(<:z\*(:>), digits,
- and quotes (\*(<:'\*(:> and \*(<:"\*(:>).
- A tag must start with a letter.
- For example, \*(<:a3'b"\*(:> is a tag.
- .Tx
- Some other signs are composite: \*(<:..\*(:>, \*(<:**\*(:>, \*(<:*/\*(:>, \*(<:/*\*(:>, \*(<:^^\*(:>,
- \*(<:<<\*(:>, \*(<:><\*(:>, \*(<:>>\*(:>, \*(<:<=\*(:>, \*(<:<>\*(:> and \*(<:>=\*(:>.
- Spaces are freely allowed between symbols, but not
- within keywords, tags, numeric-constants and composite signs.
- Sometimes spaces are required to separate keywords and tags from following
- symbols.
- For example, \*(<:cos y\*(:> is not the same as \*(<:cosy\*(:>: the latter is
- taken to be one tag.
- .St 4 UNITS
- .Xx work-space
- .Sy 4
- .Pr unit 4
- .Al
- how-to-unit
- .Al
- yield-unit
- .Al
- test-unit
- .Ps
- Units are the building blocks of a \*B ``program''.
- Users can define new commands, functions and predicates by writing a unit.
- These units reside in a work-space.
- .Pr refinement-suite 2
- .Al
- new-line\0refinement\0optional-refinement-suite
- .Ps
- When writing a unit, the specification of some parts
- (commands, expressions and tests) may be deferred by
- using a ``refinement''.
- These refinements are then specified at the end of the unit.
- .Se 3 4.1 HOW-TO-UNITS
- .Xx keyword
- .Xx user-defined-command
- .Sy 3
- .Pr how-to-unit 3
- .Al
- \*(<:HOW'TO\*(:> formal-user-defined-command\*(<::\*(:>
- .br
- command-suite
- .br
- optional-refinement-suite
- .Pr formal-user-defined-command 2
- .Sl
- keyword\0optional-formal-tail
- .Ps
- The first keyword of a formal-user-defined-command must be unique, i.e.,
- different from the first keywords of all predefined and other
- user-defined commands.
- So it is impossible to redefine the built-in commands of \*B.
- It may also not be \*(<:HOW'TO\*(:>, \*(<:YIELD\*(:>, \*(<:TEST\*(:>, \*(<:SHARE\*(:> or \*(<:ELSE\*(:>.
- Otherwise, it may be chosen freely.
- There are no restrictions on the second and further keywords.
- .Pr formal-tail 3
- .Al
- formal-parameter\0optional-formal-trailer
- .Al
- formal-trailer
- .Pr formal-trailer 2
- .Sl
- keyword\0optional-formal-tail
- .Pr formal-parameter 1
- .Sl
- tag
- .Ps
- Note that, although actual-parameters (section 5.1.16)
- and formal-operands (section 4.2) may be composite,
- formal-parameters must be simple tags.
- .Sx 5 \k1how-to-unit:
- \*(<:HOW'TO PUSH value ON stack:
- PUT value IN stack[#stack+1]\*(:>
- .Tx
- A how-to-unit defines the meaning of a new command
- (see ``user-defined-commands'', section 5.1.16).
- The above unit defines a \*(<:PUSH\*(:>\ ...\ \*(<:ON\*(:>\ ... command.
- Once the command has been defined, it may be used in the
- same way as the built-in commands.
- Other user-defined commands may be used in the body of a unit
- even if they have not yet been defined,
- though they must be defined by the time the unit is invoked.
- .Xe
- .Sa
- quit-command (5.1.11),
- share-heading (4.5),
- user-defined-commands (5.1.16).
- .Se 3 4.2 YIELD-UNITS
- .Xx "overloading of functions and predicates"
- .Xx user-defined functions
- .Xx formula
- .Xx function
- .Xx predicate
- .Xx zeroadic
- .Xx monadic
- .Xx dyadic
- .Sy 3
- .Pr yield-unit 3
- .Al
- \*(<:YIELD\*(:> formal-formula\*(<::\*(:>
- .br
- command-suite
- .br
- optional-refinement-suite
- .Pr formal-formula 4
- .Al
- formal-zeroadic-formula
- .Al
- formal-monadic-formula
- .Al
- formal-dyadic-formula
- .Pr formal-zeroadic-formula 2
- .Sl
- zeroadic-function
- .Pr formal-monadic-formula 2
- .Sl
- monadic-function\0formal-operand
- .Pr formal-dyadic-formula 2
- .Al
- formal-operand\0dyadic-function\0formal-operand
- .Ps
- Functions must not be ``overloaded'' (multiply defined),
- and a user-defined function must be represented by a tag.
- However, a given tag may be used, at the same time, for
- a dyadic-function and either a zeroadic- or a monadic-function or -predicate.
- (In other words, you may not have a function that is both monadic
- and zeroadic, for otherwise it would be impossible to decide what was meant
- in cases such as \*(<:f + 1\*(:>,
- where \*(<:f\*(:> could be either zeroadic or monadic, and the restrictions
- also apply to combinations of functions and predicates.)
- .Pr formal-operand 2
- .Sl
- single-identifier
- .Sx 5 \k1yield-unit:
- \*(<:YIELD (a, b) over (c, d):
- PUT c*c+d*d IN rr
- RETURN (a*c+b*d)/rr, (-a*d+b*c)/rr\*(:>
- .Xe
- .Tx
- A yield-unit defines the meaning of a new function
- (see ``Formulas with user-defined functions'', section 6.1.6).
- The example given above defines complex division.
- (Complex numbers are not a built-in type of \*B.)
- .br
- Functions may be zeroadic (no operands), monadic (one trailing operand)
- or dyadic (two operands, one at the left and one at the right).
- .Sa
- return-commands (5.1.12),
- share-headings (4.5),
- formulas with user-defined functions (6.1.6).
- .Se 3 4.3 TEST-UNITS
- .Xx "overloading of functions and predicates"
- .Xx user-defined-predicates
- .Xx test
- .Xx formula
- .Xx function
- .Xx predicate
- .Xx proposition
- .Xx zeroadic
- .Xx monadic
- .Xx dyadic
- .Sy 3
- .Pr test-unit 3
- .Al
- \*(<:TEST\*(:> formal-proposition\*(<::\*(:>
- .br
- command-suite
- .br
- optional-refinement-suite
- .Pr formal-proposition 4
- .Al
- formal-zeroadic-proposition
- .Al
- formal-monadic-proposition
- .Al
- formal-dyadic-proposition
- .Pr formal-zeroadic-proposition 2
- .Sl
- zeroadic-predicate
- .Pr formal-monadic-proposition 2
- .Al
- monadic-predicate\0formal-operand
- .Pr formal-dyadic-proposition 2
- .Al
- formal-operand\0dyadic-predicate\0formal-operand
- .Ps
- Like functions, predicates must not be ``overloaded'',
- though a given tag may be used, at the same time, for
- a dyadic-predicate and either a zeroadic- or a monadic-function or -predicate.
- .Sx 5 \k1test-unit:
- \*(<:TEST a subset b:
- REPORT EACH x IN a HAS x in b\*(:>
- .Xe
- .Tx
- A test-unit defines the meaning of a new predicate
- (see ``Propositions with user-defined predicates'', section 6.3.2).
- Like functions, predicates may be zeroadic, monadic or dyadic.
- .br
- Tests do not return a value, but succeed or fail via the \*(<:REPORT\*(:>,
- \*(<:SUCCEED\*(:> and \*(<:FAIL\*(:> commands.
- .Sa
- report-commands (5.1.13),
- succeed-command (5.1.14),
- fail-command (5.1.15),
- share-headings (4.5),
- propositions with user-defined predicates (6.3.2).
- .Se 4 4.4 REFINEMENTS
- .Xx keyword
- .Sy 4
- .Pr refinement 4
- .Al
- command-refinement
- .Al
- expression-refinement
- .Al
- test-refinement
- .Pr command-refinement 2
- .Sl
- keyword\*(<::\*(:> command-suite
- .Ps
- The keyword of a command-refinement must be different from the first keywords
- of all predefined commands,
- and it may also not be \*(<:HOW'TO\*(:>, \*(<:YIELD\*(:>, \*(<:TEST\*(:>, \*(<:SHARE\*(:> or \*(<:ELSE\*(:>.
- It may, however, be the same as the first keyword of a user-defined-command.
- .Sx 4 \k1command-refinement:
- \*(<:SELECT'TASK:
- PUT min tasks IN task
- REMOVE task FROM tasks\*(:>
- .Pr expression-refinement 2
- .Sl
- tag\*(<::\*(:> command-suite
- .Sx 4 expression-refinement:
- \*(<:stack'pointer:
- IF stack = {}: RETURN 0
- RETURN max keys stack\*(:>
- .Pr test-refinement 2
- .Sl
- tag\*(<::\*(:> command-suite
- .Sx 4 test-refinement:
- \*(<:special'case:
- REPORT position+d = line'length\*(:>
- .Xe
- .Tx
- Refinements support the method of ``top-down'' programming, also
- known as programming by ``stepwise refinement''.
- The body of a unit may be written using refined-commands, -expressions
- and -tests that reflect the appropriate, coarse-grained, level of
- abstraction for expressing the algorithmic intention.
- In subsequent refinements, these may be refined to
- the necessary detail, possibly in several steps.
- As with units, there are three kinds of refinements.
- The differences with units are:
- .in (\w'\(em\ 'u+3m)u
- .ti 3m
- \(em\ refinements are bound to a unit and may not be invoked
- from other units;
- .ti 3m
- \(em\ all tags known inside the unit are also known inside the
- refinement;
- .ti 3m
- \(em\ no parameters or operands can be passed when the
- refinement is invoked.
- .in 0
- {{Currently, refinements may only occur within unit bodies, and not
- in ``immediate commands''.}}
- .Sa
- refined-commands (5.1.17),
- refined-expressions (6.1.7),
- refined-tests (6.3.3).
- .Se 4 4.5 COMMAND-SUITES
- .Xx target
- .Xx local
- .Xx global
- .Xx work-space
- .Xx permanent environment
- .Xx yield-unit
- .Xx expression-refinement
- .Xx return-command
- .Xx test-unit
- .Xx test-refinement
- .Xx report-command
- .Xx succeed-command
- .Xx fail-command
- .Sy 4
- .Pr command-suite 4
- .Al
- simple-command
- .Al
- increase-indentation\0optional-share-heading
- optional-command-sequence\0decrease-indentation
- .Ps
- A command-suite may only follow the preceding colon on the same line
- if it is a simple-command.
- Otherwise, it starts on a new line, with
- all lines of the command-suite indented.
- .Sx 4 command-suite
- \*(<:SHARE name'list, abbreviation'table
- IF name in keys abbreviation'table:
- PUT abbreviation'table[name] IN name
- IF name not'in name'list:
- INSERT name IN name'list\*(:>
- .Xe
- .Pr share-heading 3
- .Al
- new-line \*(<:SHARE\*(:> identifier\0optional-share-heading
- .Ps
- Tags used as targets (variables) in a unit
- (except those that are formal-parameters)
- are by default local to the unit.
- If a target should be shared between several units,
- this can be indicated by listing the tag
- in a share-heading at the start of the unit body.
- It stands then for a global target of the work-space.
- The global targets together with their contents are also called the ``permanent
- environment'', because they survive on logging out.
- .br
- A share-heading may only occur in the command-suite of a unit (and not
- of a refinement or compound-command).
- .Sx 2 share-heading
- \*(<:SHARE name'list, abbreviation'table\*(:>
- .Xe
- .Pr command-sequence 2
- .Al
- new-line\0command\0optional-command-sequence
- .Ps
- The execution of the command-suite of a yield-unit or
- expression-refinement must end in a return-command, and return-commands
- may only occur within such command-suites.
- .Ps
- The execution of the command-suite of a test-unit or
- test-refinement must end in a report-, succeed- or fail-command, and these
- may only occur within such command-suites.
- .Sx 3 command-sequence
- \*(<:IF name in keys abbreviation'table:
- PUT abbreviation'table[name] IN name
- IF name not'in name'list:
- INSERT name IN name'list\*(:>
- .Xe
- .St 5 COMMANDS
- .Xx immediate command
- .Xx global
- .Xx interrupt key
- .Tx
- Commands may be given as ``immediate commands'', directly from
- the terminal, or may be part of a unit.
- If commands are given as immediate commands, they are obeyed
- directly.
- Any targets in the command are then interpreted as global targets
- from the permanent environment.
- Within a unit, targets are local, unless they have been listed
- in a share-heading (see above).
- .br
- If the user presses the interrupt key while a command is executing,
- execution is aborted, and the user is prompted for another immediate command.
- .Sy 3
- .Pr command 3
- .Al
- simple-command
- .Al
- control-command
- .Se 3 5.1 SIMPLE-COMMANDS
- .Sy 3
- .Pr simple-command 3
- .Al
- check-command
- .Al
- write-command
- .Al
- read-command
- .Al
- put-command
- .Al
- draw-command
- .Al
- choose-command
- .Al
- set-random-command
- .Al
- remove-command
- .Al
- insert-command
- .Al
- delete-command
- .Al
- terminating-command
- .Al
- user-defined-command
- .Al
- refined-command
- .Pr terminating-command 3
- .Al
- quit-command
- .Al
- return-command
- .Al
- report-command
- .Al
- succeed-command
- .Al
- fail-command
- .Se 2 5.1.1 CHECK-COMMANDS
- .Sy 2
- .Pr check-command 2
- .Sl
- \*(<:CHECK\*(:> test
- .Sx 3 \k1check-command:
- \*(<:CHECK i >= 0 AND j >= 0 AND i+j <= n\*(:>
- .Xe
- .Tx
- When a check-command is executed, its test is tested.
- If the test fails, an error is reported and execution halts.
- Otherwise, no message is given and execution continues.
- Check-commands may be used, for example, to check the requirements of
- parameters or operands on entry to a unit.
- The liberal use of check-commands helps to get programs correct quickly.
- .Se 3 5.1.2 WRITE-COMMANDS
- .Xx convert to a text
- .Xx permanent environment
- .Xx interrupt key
- .Sy 3
- .Pr write-command 3
- .Al
- \*(<:WRITE\*(:> new-liners
- .Al
- \*(<:WRITE\*(:> optional-new-liners\0expression\0optional-new-liners
- .Pr new-liners 2
- .Sl
- \*(<:/\*(:> optional-new-liners
- .Ex 3
- \k1write-commands:
- \h'|\n1u'\*(<:WRITE //\*(:>
- \h'|\n1u'\*(<:WRITE // 'Give a value in the range 1 through `n`: '\*(:>
- .Tx
- The expression is converted to a text and written to the screen.
- Each \*(<:/\*(:> gives a transition to a new line.
- Note that you write no comma before or after the \*(<:/\*(:>s.
- .br
- With the exception of adjacent texts,
- values that are adjacent are written separated by a space.
- Compounds within other values (within lists, tables or other compounds)
- are written with commas between their fields,
- and where necessary, the whole surrounded by brackets.
- Similarly, inner texts are written enclosed by quotes.
- Compounds and texts not within other values are output without commas,
- brackets and quotes.
- Thus,
- .Di 2
- \*(<:WRITE 0, 1, ',', 2, '!', '!', 3
- WRITE {1; 2}, {['a','b']:('b','a'); ['b','a']:('a','b')} /\*(:>
- .Ed
- gives
- .Di 1
- \*(<:0 1 , 2 !! 3 {1; 2} {['a', 'b']: ('b', 'a'); ['b', 'a']: ('a', 'b')}\*(:>
- .Ed
- For formatting purposes, see the operators \*(<:>>\*(:>, \*(<:<<\*(:>, and \*(<:><\*(:>
- in section 6.1.6, ``Functions on Texts'',
- and the conversions in text-displays in section 6.1.5, ``Displays''.
- .Se 3 5.1.3 READ-COMMANDS
- .Sy 3
- .Pr read-command 4
- .Al
- \*(<:READ\*(:> target \*(<:EG\*(:> expression
- .Al
- \*(<:READ\*(:> target \*(<:RAW\*(:>
- .Ex 3
- read-commands:
- \*(<:READ n, s EG 0, ''
- READ line RAW\*(:>
- .Xe
- .Tx
- The execution of a read-command prompts the user
- to supply one input line.
- .br
- If an \*(<:EG\*(:> part is present, the input is interpreted as an
- \fIexpression\fP of the same type as the expression following \*(<:EG\*(:>.
- (Usually, the example expression will consist of constants,
- but other expressions are also allowed.)
- The input expression is evaluated in the permanent environment
- (so local tags of units cannot be used) and put in the target.
- To input a text-display (literal), text quotes are required.
- .br
- If \*(<:RAW\*(:> is specified, the target must be a text target.
- The input line is put in the target literally.
- No text quotes are needed.
- .br
- If the user presses the interrupt key instead of supplying a value,
- the read-command, and in fact the whole program, is aborted.
- This is useful for entering a sequence of data of unspecified length.
- .Se 3 5.1.4 PUT-COMMANDS
- .Xx target
- .Xx location
- .Xx type
- .Sy 3
- .Pr put-command 3
- .Sl
- \*(<:PUT\*(:> expression \*(<:IN\*(:> target
- .Sx 3 \k1put-command:
- \*(<:PUT a+1, ({}, {1..a}) IN a, b\*(:>
- .Xe
- .Tx
- The value of the expression is put in the target.
- This means that the value will be held in a location
- for the target, until a different value is put in the target,
- or the target is deleted.
- If no such location exists already, it is created on
- the spot.
- Here, as in other cases, the types must agree.
- {{This is currently not checked in general.}}
- See also the sections on various kinds of targets below (section 6.2).
- .Se 2 5.1.5 DRAW-COMMANDS
- .Xx random
- .Xx number
- .Sy 2
- .Pr draw-command 2
- .Sl
- \*(<:DRAW\*(:> target
- .Sx 3 \k1draw-command:
- \*(<:DRAW r\*(:>
- .Xe
- .Tx
- A random approximate number
- (from \*(<:~0\*(:> up to, but not including, \*(<:~1\*(:>)
- is drawn and put in the target.
- .Se 4 5.1.6 CHOOSE-COMMANDS
- .Xx text, list or table
- .Xx random
- .Xx character
- .Xx list entry
- .Xx associate
- .Sy 4
- .Pr choose-command 4
- .Sl
- \*(<:CHOOSE\*(:> target \*(<:FROM\*(:> expression
- .Sx 3 \k1choose-command:
- \*(<:CHOOSE exit FROM exits[current'room]\*(:>
- .Xe
- .Tx
- The expression must have a text, list or table as value.
- This value must not be empty.
- An item is drawn at random from the value
- (characters from a text, entries from a list and associates
- from a table)
- and put in the target.
- The item is not removed from the value.
- .Se 2 5.1.7 SET-RANDOM-COMMANDS
- .Xx random
- .Sy 2
- .Pr set-random-command 2
- .Sl
- \*(<:SET'RANDOM\*(:> expression
- .Sx 3 \k1set-random-command:
- \*(<:SET'RANDOM 'Monte Carlo', run\*(:>
- .Xe
- .Tx
- The (pseudo-)random sequence
- used for draw- and choose-commands
- is reset to a point, depending on the
- value of the expression.
- .Se 3 5.1.8 REMOVE-COMMANDS
- .Xx list entry
- .Sy 3
- .Pr remove-command 3
- .Sl
- \*(<:REMOVE\*(:> expression \*(<:FROM\*(:> target
- .Sx 3 \k1remove-command:
- \*(<:REMOVE task FROM tasks\*(:>
- .Xe
- .Tx
- The target must hold a list, and the value of the expression must be
- an entry of that list.
- The entry is removed.
- If it was present more than once, only one instance is removed.
- .Se 3 5.1.9 INSERT-COMMANDS
- .Xx list entry
- .Sy 3
- .Pr insert-command 3
- .Sl
- \*(<:INSERT\*(:> expression \*(<:IN\*(:> target
- .Sx 3 \k1insert-command:
- \*(<:INSERT new'task IN tasks\*(:>
- .Xe
- .Tx
- The target must hold a list.
- The value of the expression is inserted as a list entry.
- If that entry was already present, one more instance will be present.
- .Se 2 5.1.10 DELETE-COMMANDS
- .Xx location
- .Xx table entry
- .Xx table-selection-target
- .Sy 2
- .Pr delete-command 2
- .Sl
- \*(<:DELETE\*(:> target
- .Sx 3 \k1delete-command:
- \*(<:DELETE t[i], u[i, j]\*(:>
- .Xe
- .Tx
- The location for the target ceases to exist.
- If a multiple-target is given, all its single-targets are deleted.
- If a table-selection-target is given, the table must contain the key
- that is used as selector.
- The table entry with that key is then deleted from the table.
- It is an error to delete a trimmed-text-target (e.g., \*(<:t@2\*(:>).
- .Se 2 5.1.11 QUIT-COMMAND
- .Xx how-to-unit
- .Xx command-refinement
- .Xx immediate-command
- .Xx permanent environment
- .Sy 2
- .Pr quit-command 2
- .Sl
- \*(<:QUIT\*(:>
- .Ps
- A quit-command may only occur in the command-suite of a
- how-to-unit or command-refinement, or as an immediate command.
- .Sx 3 \k1quit-command:
- \*(<:QUIT\*(:>
- .Xe
- .Tx
- The execution of a quit-command causes the termination of the execution
- of the how-to-unit or command-refinement in whose command-suite
- it occurs.
- If it occurs in a command-refinement, the execution of
- the invoking refined-command is thereby terminated and the further
- execution continues as if the refined-command had terminated normally.
- Otherwise, the execution of
- the invoking user-defined-command is terminated and the further
- execution continues similarly.
- .br
- Given as an immediate command, \*(<:QUIT\*(:> terminates the current
- session.
- All units and targets in the permanent environment
- survive and can be used again at the next session.
- .Se 2 5.1.12 RETURN-COMMANDS
- .Xx expression-refinement
- .Xx user-defined-function
- .Xx refined-expression
- .Xx yield-unit
- .Sy 2
- .Pr return-command 2
- .Sl
- \*(<:RETURN\*(:> expression
- .Sx 3 \k1return-command:
- \*(<:RETURN (a*c+b*d)/rr, (-a*d+b*c)/rr\*(:>
- .Xe
- .Tx
- The execution of a return-command causes the termination of the execution
- of the yield-unit or expression-refinement in whose command-suite
- it occurs.
- The value of the expression is returned as the value of the invoking
- user-defined function or refined-expression.
- Return-commands may only occur within the command-suite of a
- yield-unit or expression-refinement.
- .Se 2 5.1.13 REPORT-COMMANDS
- .Xx test-unit
- .Xx test-refinement
- .Xx user-defined-predicate
- .Xx refined-test
- .Xx bound tags
- .Pr report-command 2
- .Sl
- \*(<:REPORT\*(:> test
- .Sx 3 \k1report-command:
- \*(<:REPORT i in keys t\*(:>
- .Xe
- .Tx
- The execution of a report-command causes the termination of the execution
- of the test-unit or test-refinement in whose command-suite
- it occurs.
- The invoking user-defined predicate or refined-test
- succeeds/fails if the test of the report-command succeeds/fails.
- If the invoker is a test-refinement,
- any bound tags set by a for-command (see section 5.2.4) or
- a quantification (section 6.3.7) will temporarily survive,
- as described under REFINED-TESTS (section 6.3.3).
- .br
- Report-commands may only occur within the command-suite of a
- test-unit or test-refinement.
- .br
- The command ``\*(<:REPORT\*(:> test'' is equivalent to
- .Di 3
- \*(<:SELECT:
- \*(:>test\*(<:: SUCCEED
- ELSE: FAIL\*(:>
- .Ed
- .Se 2 5.1.14 SUCCEED-COMMAND
- .Xx test-unit
- .Xx test-refinement
- .Xx user-defined-predicate
- .Xx refined-test
- .Xx bound tags
- .Sy 2
- .Pr succeed-command 2
- .Sl
- \*(<:SUCCEED\*(:>
- .Sx 3 \k1succeed-command:
- \*(<:SUCCEED\*(:>
- .Xe
- .Tx
- The execution of a succeed-command causes the termination of the execution
- of the test-unit or test-refinement in whose command-suite
- it occurs.
- The invoking user-defined predicate or refined-test succeeds.
- As with report-commands, bound tags temporarily survive.
- .br
- Succeed-commands may only occur within the command-suite of a
- test-unit or test-refinement.
- .br
- The command \*(<:SUCCEED\*(:> is equivalent to \*(<:REPORT 0 = 0\*(:>.
- .Se 2 5.1.15 FAIL-COMMAND
- .Xx test-unit
- .Xx test-refinement
- .Xx user-defined-predicate
- .Xx refined-test
- .Xx bound tags
- .Sy 2
- .Pr fail-command 2
- .Sl
- \*(<:FAIL\*(:>
- .Sx 3 \k1fail-command:
- \*(<:FAIL\*(:>
- .Xe
- .Tx
- The execution of a fail-command causes the termination of the execution
- of the test-unit or test-refinement in whose command-suite
- it occurs.
- The invoking user-defined predicate or refined-test fails.
- As with report-commands, bound tags temporarily survive.
- .br
- Fail-commands may only occur within the command-suite of a
- test-unit or test-refinement.
- .br
- The command \*(<:FAIL\*(:> is equivalent to \*(<:REPORT 0 = 1\*(:>.
- .Se 2 5.1.16 USER-DEFINED-COMMANDS
- .Xx keyword
- .Xx how-to-unit
- .Xx quit-command
- .Sy 2
- .Pr user-defined-command 2
- .Sl
- keyword\0optional-actual-parameter\0optional-trailer
- .Pr trailer 2
- .Sl
- keyword\0optional-actual-parameter\0optional-trailer
- .Pr actual-parameter 2
- .Al
- identifier
- .Al
- target
- .Al
- expression
- .Ps
- The keywords and actual-parameters must correspond one to one to those
- of the formal-user-defined-command of one unique how-to-unit.
- .Ex 6
- \k1user-defined-commands:
- \h'|\n1u'\*(<:CLEAN'UP\*(:>
- \h'|\n1u'\*(<:DRINK me\*(:>
- \h'|\n1u'\*(<:TURN a UPSIDE DOWN\*(:>
- \h'|\n1u'\*(<:PUSH v ON operand'stack\*(:>
- .Xe
- .Tx
- A user-defined-command is executed in the following steps:
- .in \w'2.\ 'u
- .ti 0
- 1.\ Any local tags in the how-to-unit that might clash with tags currently
- in use are systematically replaced by other tags that do not cause conflict.
- .ti 0
- 2.\ Each actual-parameter is placed between parentheses \*(<:(\*(:> and \*(<:)\*(:>
- and then
- substituted throughout the unit for the corresponding formal-parameter.
- .ti 0
- 3.\ The command-suite of the unit, thus modified, is executed.
- .in 0
- The execution of the user-defined-command is complete when the execution
- of this command-suite terminates (normally, or because of the execution
- of a quit-command).
- After the execution is complete,
- the local tags of the unit are no longer accessible.
- .Se 2 5.1.17 REFINED-COMMANDS
- .Xx keyword
- .Xx command-refinement
- .Xx quit-command
- .Sy 2
- .Pr refined-command 2
- .Sl
- keyword
- .Ps
- The keyword of a refined-command must occur as the keyword of one
- command-refinement in the unit
- in which it occurs.
- That command-refinement specifies the meaning of the refined-command.
- .Sx 3 \k1refined-command:
- \*(<:REMOVE'MULTIPLES\*(:>
- .Xe
- .Tx
- A refined-command is executed by executing
- the command-suite of the corresponding command-refinement.
- The execution of the refined-command is complete when the execution
- of this command-suite terminates
- (normally, or because of the execution of a quit-command).
- .Se 5 5.2 CONTROL-COMMANDS
- .Sy 5
- .Pr control-command 5
- .Al
- if-command
- .Al
- select-command
- .Al
- while-command
- .Al
- for-command
- .Se 2 5.2.1 IF-COMMANDS
- .Sy 2
- .Pr if-command 2
- .Sl
- \*(<:IF\*(:> test\*(<::\*(:> command-suite
- .Sx 3 \k1if-command:
- \*(<:IF i < 0: PUT -i, -j IN i, j\*(:>
- .Xe
- .Tx
- The test is tested.
- If it succeeds, the command-suite is executed;
- if it fails, the command-suite is not executed.
- .br
- (If something should be executed on failure too, or there are
- more alternatives, you should use a select-command instead.)
- .br
- The command
- ``\*(<:IF\*(:> test\*(<::\*(:> command-suite''
- is equivalent to:
- .Di 3
- \*(<:SELECT:
- \*(:>test\*(<:: \*(:>command-suite\*(<:
- ELSE: \\do nothing.\*(:>
- .Ed
- .Se 2 5.2.2 SELECT-COMMANDS
- .Sy 2
- .Pr select-command 2
- .Sl
- \*(<:SELECT:\*(:> alternative-suite
- .Pr alternative-suite 3
- .Al
- increase-indentation\0new-line\0alternative-sequence\0decrease-indentation
- .Pr alternative-sequence 4
- .Al
- single-alternative
- .Al
- else-alternative
- .Al
- single-alternative\0new-line\0alternative-sequence
- .Pr single-alternative 2
- .Sl
- test\*(<::\*(:> command-suite
- .Pr else-alternative 2
- .Sl
- \*(<:ELSE:\*(:> command-suite
- .Eo 5 select-commands:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\k2\":
- \h'|\n1u'\*(<:SELECT:\*(:> \h'|\n2u'\*(<:SELECT:\*(:>
- \h'|\n1u'\*(<: a < 0: RETURN -a\*(:> \h'|\n2u'\*(<: a < 0: RETURN -a\*(:>
- \h'|\n1u'\*(<: a >= 0: RETURN a\*(:> \h'|\n2u'\*(<: ELSE: RETURN a\*(:>
- .Xe
- .Tx
- The tests of the alternatives are tested one by one,
- starting with the first and proceeding downwards, until one
- is found that succeeds.
- The corresponding command-suite is then executed.
- \*(<:ELSE\*(:> may be used in the final alternative as a test that always succeeds.
- If all the tests fail, an error is reported.
- .Se 2 5.2.3 WHILE-COMMANDS
- .Xx terminating command
- .Sy 2
- .Pr while-command 2
- .Sl
- \*(<:WHILE\*(:> test\*(<::\*(:> command-suite
- .Sx 3 \k1while-command:
- \*(<:WHILE x > 1: PUT x/10, c+1 IN x, c\*(:>
- .Xe
- .Tx
- If the test succeeds, the command-suite is executed, and the
- while-command is repeated, and so on, until the test fails,
- or until an escape is forced by a terminating command.
- If the test fails the very first time, the command-suite is
- not executed at all.
- .Se 3 5.2.4 FOR-COMMANDS
- .Xx text, list or table
- .Xx character
- .Xx list entry
- .Xx associate
- .Xx target
- .Xx bound tags
- .Sy 3
- .Pr for-command 3
- .Sl
- \*(<:FOR\*(:> in-ranger\*(<::\*(:> command-suite
- .Pr in-ranger 2
- .Sl
- identifier \*(<:IN\*(:> expression
- .Sx 3 \k1for-command:
- \*(<:FOR i, j IN keys t: PUT t[i, j] IN t'[j, i]\*(:>
- .Xe
- .Tx
- The value of the expression must be a text, list or table.
- One by one, each item of that value
- (characters for a text, list entries for a list and associates for a table)
- is put in the identifier, and the command-suite executed.
- For example,
- .Di 1
- \*(<:FOR c IN 'ABC': WRITE 'letter is', c /\*(:>
- .Ed
- is equivalent to
- .Di 3
- \*(<:WRITE 'letter is', 'A' /
- WRITE 'letter is', 'B' /
- WRITE 'letter is', 'C' /\*(:>
- .Ed
- If \*(<:t\*(:> is a table, then
- ``\*(<:FOR a IN t: TREAT a\*(:>''
- treats the associates of \*(<:t\*(:> in the same way as
- .Di 3
- \*(<:FOR k IN keys t:
- PUT t[k] IN a
- TREAT a\*(:>
- .Ed
- The tags of the identifier of a for-command may not be used as targets
- or target-contents
- outside such a for-command.
- They are ``bound tags'', and lose their meaning outside the
- for-command.
- There is one exception to this rule:
- if a for-command is used in a test-refinement, and within
- the for-command a report-, succeed- or fail-command is
- executed, the currently bound tags will temporarily survive
- as described under REFINED-TESTS (section 6.3.3).
- .Sa
- quantifications (6.3.7).
-